﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NewRetail.Application.Components.Dashboard.Model;
using NewRetail.Application.Components.Platform.Entity;
using NewRetail.Application.Components.Warehouse.Entity;
using NewRetail.Application.Core;
using NewRetail.Application.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace NewRetail.Application.Components.Dashboard
{
    /// <summary>
    /// 大屏数据接口
    /// </summary>
    public interface IDashboardService : IApplicationService
    {
        /// <summary>
        /// 基础信息概况
        /// </summary>
        /// <returns></returns>
        Task<BaseInfoSummaryDto> BasicInfoSummary();
        /// <summary>
        /// 今日销售数据
        /// </summary>
        /// <returns></returns>
        Task<TodaySaleDto> TodaySaleInfo();
        /// <summary>
        /// 近7日销售
        /// </summary>
        /// <returns></returns>
        Task<LastSevenDaySaleDto> LastSevenDaySaleInfo();
        /// <summary>
        /// 本年度销售
        /// </summary>
        /// <returns></returns>
        Task<YearSaleDto> YearSaleInfo();
        /// <summary>
        /// 今日各门店销售
        /// </summary>
        /// <returns></returns>
        Task<TodayStoreSaleDto> TodayStoreSaleInfo();
        /// <summary>
        /// 今日支付方式占比数据
        /// </summary>
        /// <returns></returns>
        Task<IEnumerable<PaymentMethodSaleDto>> PaymentWaySaleInfo();
        /// <summary>
        /// 购买渠道占比数据
        /// </summary>
        /// <returns></returns>
        Task<IEnumerable<BuyChannelSaleDto>> BuyChannelSaleInfo();
    }

    /// <summary>
    /// 大屏数据的实现
    /// </summary>
    public class DashboardService : ApplicationService, IDashboardService
    {
        #region Field
        //private readonly IRepository<Warehouse.Entity.Warehouse> _warehouseRepository;
        private readonly IRepository<PosSalesFlow> _posSalesFlowRepository;
        //private readonly IRepository<PosMember> _posMemberRepository;
        private readonly ILogger _logger;
        #endregion

        #region 构造函数
        public DashboardService(IRepository<PosSalesFlow> posSalesFlowRepository, /*IRepository<Warehouse.Entity.Warehouse> warehouseRepository, 
            IRepository<PosMember> posMemberRepository,*/
            ILogger<DashboardService> logger)
        {
            //_warehouseRepository = warehouseRepository;
            _posSalesFlowRepository = posSalesFlowRepository;
            //_posMemberRepository = posMemberRepository;
            _logger = logger;
        }
        #endregion

        #region Implementation of ISignatureService

        #region 基础信息概况
        /// <summary>
        /// 基础信息概况
        /// </summary>
        /// <returns></returns>
        public async Task<BaseInfoSummaryDto> BasicInfoSummary()
        {
            var baseInfoSummary = new BaseInfoSummaryDto();
            try
            {
                //var dbWarehouse = await _warehouseRepository.GetDbContextAsync();
                //var dbPosMember = await _posMemberRepository.GetDbContextAsync();
                var db = await _posSalesFlowRepository.GetDbContextAsync();
                //获取门店
                var warehouseList = await db.Set<Warehouse.Entity.Warehouse>().Where(x => x.isEnable == true).AsNoTracking()?.ToListAsync();
                //门店数量
                baseInfoSummary.storeCount = warehouseList == null ? 0 : warehouseList.Count();
                //获取会员
                var posMemberList = await db.Set<PosMember>().IgnoreQueryFilters().AsNoTracking()?.ToListAsync();
                //总会员数量
                baseInfoSummary.memberCount = posMemberList == null ? 0 : posMemberList.Count();
                //当月第一天
                var beginDate = DateTime.Now.AddDays(1 - DateTime.Now.Day).Date;
                //当月最后一天
                var endDate = DateTime.Now.AddDays(1 - DateTime.Now.Day).Date.AddMonths(1).AddSeconds(-1);
                //当年第一天
                var currYearFirstDate = new DateTime(DateTime.Now.Year, 1, 1, 0, 0, 0);
                //当年最后一天
                var currYearEndDate = new DateTime(DateTime.Now.Year, 12, 31, 23, 59, 59);
                //获取本月销售
                var posSalesFlowYearMonthList = await db.Set<PosSalesFlow>().Where(x => x.operateTime >= beginDate && x.operateTime <= endDate).AsNoTracking()?.ToListAsync();
                //本月销售量(deprecate)
                baseInfoSummary.monthSaleCount = posSalesFlowYearMonthList == null ? 0 : posSalesFlowYearMonthList.Sum(x => x.saleQuantity);
                
                //获取本月的采购
                var inOrOutWarehouseYearMonthList = await db.Set<InOutWarehousing>().Where(x => x.receiptDate >= beginDate && x.receiptDate <= endDate).AsNoTracking()?.ToListAsync();
                //本月采购额
                baseInfoSummary.monthPurchaseAmount = inOrOutWarehouseYearMonthList == null ? 0 : inOrOutWarehouseYearMonthList.Sum(x => x.inOrOut == (int)InOrOutEnum.IN ? (x.curSalePrice * x.quantity) : -(x.curSalePrice * x.quantity));

                //本月销售额
                baseInfoSummary.monthSaleAmount = posSalesFlowYearMonthList == null ? 0 : posSalesFlowYearMonthList.Sum(x => x.saleMoney);                
                //获取当前年度销售
                var posSalesFlowYearList = await db.Set<PosSalesFlow>().Where(x => x.operateTime >= currYearFirstDate && x.operateTime <= currYearEndDate).AsNoTracking()?.ToListAsync();
                //年度总销售量(deprecate)
                baseInfoSummary.yearSaleCount = posSalesFlowYearList == null ? 0 : posSalesFlowYearList.Sum(x => x.saleQuantity);
                //获取当前年度采购
                var inOrOutWarehouseYearList = await db.Set<InOutWarehousing>().Where(x => x.receiptDate >= currYearFirstDate && x.receiptDate <= currYearEndDate).AsNoTracking()?.ToListAsync();
                //年度采购金额
                baseInfoSummary.yearPurchaseAmount= inOrOutWarehouseYearList == null ? 0 : inOrOutWarehouseYearList.Sum(x => x.inOrOut == (int)InOrOutEnum.IN ? (x.curSalePrice * x.quantity) : -(x.curSalePrice * x.quantity));

                //年度总销售额
                baseInfoSummary.yearSaleAmount = posSalesFlowYearList == null ? 0 : posSalesFlowYearList.Sum(x => x.saleMoney);
            }
            catch (Exception e)
            {
                _logger.LogError(message: e.Message, exception: e);
            }
            return baseInfoSummary;

        }
        #endregion

        #region 今日销售数据
        /// <summary>
        /// 今日销售数据
        /// </summary>
        /// <returns></returns>
        public async Task<TodaySaleDto> TodaySaleInfo()
        {
            var todaySale = new TodaySaleDto();
            try
            {
                var db = await _posSalesFlowRepository.GetDbContextAsync();
                //今日开始时间
                var currBeginDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
                //今日结束时间
                var currEndDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59);
                //获取今日销售
                var posSalesFlowTodayList = await db.Set<PosSalesFlow>().Where(x => x.operateTime >= currBeginDate && x.operateTime <= currEndDate).AsNoTracking()?.ToListAsync();
                //今日销售量
                todaySale.todaySaleCount = posSalesFlowTodayList.Count == 0 ? 0 : posSalesFlowTodayList.Sum(x => x.saleQuantity);
                //今日销售额
                todaySale.todaySaleAmount = posSalesFlowTodayList.Count == 0 ? 0 : posSalesFlowTodayList.Sum(x => x.saleMoney);
            }
            catch (Exception e)
            {
                _logger.LogError(message: e.Message, exception: e);
            }
            return todaySale;

        }
        #endregion

        #region 近7日销售
        /// <summary>
        /// 近7日销售
        /// </summary>
        /// <returns></returns>
        public async Task<LastSevenDaySaleDto> LastSevenDaySaleInfo()
        {
            var lastSevenDaySale = new LastSevenDaySaleDto();
            try
            {
                var db = await _posSalesFlowRepository.GetDbContextAsync();
                var dtNow = DateTime.Now;
                var beforeSevenDate = DateTime.Now.AddDays(-6);
                //开始时间
                var beforeSevenBeginDate = new DateTime(beforeSevenDate.Year, beforeSevenDate.Month, beforeSevenDate.Day, 0, 0, 0);
                //结束时间
                var beforeSevenEndDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59);
                //获取近7日销售
                var posSalesFlowBeforeSevenList = await db.Set<PosSalesFlow>().Where(x => x.operateTime >= beforeSevenBeginDate && x.operateTime <= beforeSevenEndDate).AsNoTracking()?.ToListAsync();
                List<string> xDataList = new List<string>();
                List<decimal> saleCountDataList = new List<decimal>();
                List<decimal> saleAmountDataList = new List<decimal>();
                var computeSaleResult = posSalesFlowBeforeSevenList.GroupBy(p => new { saleDate = p.operateTime.ToString("yyyy-MM-dd") }).Select(p => new
                {
                    saleDate = p.Key.saleDate,
                    saleQuantity = p.Sum(x => x.saleQuantity),
                    saleAmount = p.Sum(x => x.saleMoney)
                }).ToList();
                //初始化今天之前7天的列表
                for (int i = 6; i >= 0; i--)
                {
                    var dtDate = dtNow.AddDays(-i).ToString("yyyy-MM-dd");
                    xDataList.Add(dtDate);
                    //销售量
                    var saleQuantity = computeSaleResult.Count == 0 ? 0 : computeSaleResult.Where(x => x.saleDate.CompareTo(dtDate) == 0).Sum(x => x.saleQuantity);
                    saleCountDataList.Add(saleQuantity);
                    //销售额
                    var saleMoney = computeSaleResult.Count == 0 ? 0 : computeSaleResult.Where(x => x.saleDate.CompareTo(dtDate) == 0).Sum(x => x.saleAmount);
                    saleAmountDataList.Add(saleMoney);
                }
                //最终转换赋值
                lastSevenDaySale.xData = xDataList.ToArray();
                lastSevenDaySale.saleCountData = saleCountDataList.ToArray();
                lastSevenDaySale.saleAmountData = saleAmountDataList.ToArray();
            }
            catch (Exception e)
            {
                _logger.LogError(message: e.Message, exception: e);
            }
            return lastSevenDaySale;

        }
        #endregion

        #region 本年度销售
        /// <summary>
        /// 本年度销售
        /// </summary>
        /// <returns></returns>
        public async Task<YearSaleDto> YearSaleInfo()
        {
            var yearSale = new YearSaleDto();
            try
            {
                var db = await _posSalesFlowRepository.GetDbContextAsync();
                //当年第一天
                var currYearFirstDate = new DateTime(DateTime.Now.Year, 1, 1, 0, 0, 0);
                //当年最后一天
                var currYearEndDate = new DateTime(DateTime.Now.Year, 12, 31, 23, 59, 59);
                //获取本年度销售
                var posSalesFlowYearList = await db.Set<PosSalesFlow>().Where(x => x.operateTime >= currYearFirstDate && x.operateTime <= currYearEndDate).AsNoTracking()?.ToListAsync();
                List<decimal> saleCountDataList = new List<decimal>();
                List<decimal> saleAmountDataList = new List<decimal>();
                var computeSaleResult = posSalesFlowYearList.GroupBy(p => new { saleYearMonth = p.operateTime.ToString("yyyy-MM") }).Select(p => new
                {
                    saleYearMonth = p.Key.saleYearMonth,
                    saleQuantity = p.Sum(x => x.saleQuantity),
                    saleAmount = p.Sum(x => x.saleMoney)
                }).ToList();
                //初始化本年的列表
                for (int i = 1; i <= 12; i++)
                {
                    var cYearMonth = string.Join("-", DateTime.Now.Year.ToString(), i.ToString().PadLeft(2, '0'));
                    //销售量
                    var saleQuantity = computeSaleResult.Count == 0 ? 0 : computeSaleResult.Where(x => x.saleYearMonth.CompareTo(cYearMonth) == 0).Sum(x => x.saleQuantity);
                    saleCountDataList.Add(saleQuantity);
                    //销售额
                    var saleMoney = computeSaleResult.Count == 0 ? 0 : computeSaleResult.Where(x => x.saleYearMonth.CompareTo(cYearMonth) == 0).Sum(x => x.saleAmount);
                    saleAmountDataList.Add(saleMoney);
                }
                //最终转换赋值
                yearSale.saleCountData = saleCountDataList.ToArray();
                yearSale.saleAmountData = saleAmountDataList.ToArray();
            }
            catch (Exception e)
            {
                _logger.LogError(message: e.Message, exception: e);
            }
            return yearSale;

        }
        #endregion

        #region 今日各门店销售
        /// <summary>
        /// 今日各门店销售
        /// </summary>
        /// <returns></returns>
        public async Task<TodayStoreSaleDto> TodayStoreSaleInfo()
        {
            var todayStoreSaleDto = new TodayStoreSaleDto();
            try
            {
                //var dbWarehouse = await _warehouseRepository.GetDbContextAsync();
                var db = await _posSalesFlowRepository.GetDbContextAsync();
                //今日开始时间
                var currBeginDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
                //今日结束时间
                var currEndDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59);
                //获取门店
                var storeList = await db.Set<Warehouse.Entity.Warehouse>().Where(x => x.isEnable == true).AsNoTracking()?.ToListAsync();
                //获取今日各门店销售
                var posSalesFlowStoreList = await db.Set<PosSalesFlow>().Where(x => x.operateTime >= currBeginDate && x.operateTime <= currEndDate).AsNoTracking()?.ToListAsync();
                List<string> xDataList = new List<string>();
                List<decimal> saleCountDataList = new List<decimal>();
                List<decimal> saleAmountDataList = new List<decimal>();
                var computeSaleResult = posSalesFlowStoreList.GroupBy(p => new { warehouseId = p.warehouseID }).Select(p => new
                {
                    warehouseId = p.Key.warehouseId,
                    //warehouseName = storeList.FirstOrDefault(a=>a.Id==p.Key.warehouseId).warehouseName,
                    saleQuantity = p.Sum(x => x.saleQuantity),
                    saleAmount = p.Sum(x => x.saleMoney)
                }).ToList();
                //初始列表
                foreach (var item in storeList)
                {
                    var warehouseName = item.warehouseName;
                    var warehouseId = item.Id;
                    xDataList.Add(warehouseName);
                    //销售量
                    var saleQuantity = computeSaleResult.Count == 0 ? 0 : computeSaleResult.Where(x => x.warehouseId == warehouseId).Sum(x => x.saleQuantity);
                    saleCountDataList.Add(saleQuantity);
                    //销售额
                    var saleMoney = computeSaleResult.Count == 0 ? 0 : computeSaleResult.Where(x => x.warehouseId == warehouseId).Sum(x => x.saleAmount);
                    saleAmountDataList.Add(saleMoney);
                }
                //最终转换赋值
                todayStoreSaleDto.xData = xDataList.ToArray();
                todayStoreSaleDto.saleCountData = saleCountDataList.ToArray();
                todayStoreSaleDto.saleAmountData = saleAmountDataList.ToArray();
            }
            catch (Exception e)
            {
                _logger.LogError(message: e.Message, exception: e);
            }
            return todayStoreSaleDto;

        }
        #endregion

        #region 今日支付方式占比数据
        /// <summary>
        /// 今日支付方式占比数据
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<PaymentMethodSaleDto>> PaymentWaySaleInfo()
        {
            var paymentWaySale = new List<PaymentMethodSaleDto>();
            try
            {
                var db = await _posSalesFlowRepository.GetDbContextAsync();
                //今日开始时间
                var currBeginDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
                //今日结束时间
                var currEndDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59);
                var payWayList = new string[] {
                    Enum.GetName(typeof(PayWayEnum), PayWayEnum.A),
                    Enum.GetName(typeof(PayWayEnum), PayWayEnum.Z),
                    Enum.GetName(typeof(PayWayEnum), PayWayEnum.W),
                    Enum.GetName(typeof(PayWayEnum), PayWayEnum.Y),
                    Enum.GetName(typeof(PayWayEnum), PayWayEnum.D),
                    Enum.GetName(typeof(PayWayEnum), PayWayEnum.X2),
                    Enum.GetName(typeof(PayWayEnum), PayWayEnum.Other),
                    Enum.GetName(typeof(PayWayEnum), PayWayEnum.C)
                };
                //获取今日销售支付方式，去掉找零，抹零等
                var posPayFlowTodayList = await db.Set<PosPayFlow>().Where(x => x.payTime >= currBeginDate && x.payTime <= currEndDate && payWayList.Contains(x.payWay)).AsNoTracking()?.ToListAsync();
                var computeSaleResult = posPayFlowTodayList.GroupBy(p => new { flowNo = p.flowNo, payWay = p.payWay }).Select(p => new
                {
                    payWay = p.Key.payWay,
                    saleCount = p.Count()
                }).ToList();
                //列表
                foreach (var item in payWayList)
                {
                    //字符串转枚举
                    var payWayEnum = (PayWayEnum)Enum.Parse(typeof(PayWayEnum), item);
                    var payWayName = UtilsHelper.GetEnumDesc(payWayEnum);
                    paymentWaySale.Add(new PaymentMethodSaleDto()
                    {
                        payWay = item,
                        payWayName = payWayName,
                        saleCount = computeSaleResult.FirstOrDefault(x => x.payWay == item) == null ? 0 : computeSaleResult.FirstOrDefault(x => x.payWay == item).saleCount
                    });
                }
            }
            catch (Exception e)
            {
                _logger.LogError(message: e.Message, exception: e);
            }
            return paymentWaySale;

        }
        #endregion

        #region 购买渠道占比数据
        /// <summary>
        /// 购买渠道占比数据
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<BuyChannelSaleDto>> BuyChannelSaleInfo()
        {
            var buyChannelSale = new List<BuyChannelSaleDto>();
            try
            {
                var db = await _posSalesFlowRepository.GetDbContextAsync();
                //今日开始时间
                var currBeginDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
                //今日结束时间
                var currEndDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59);
                var buyChannelList = new string[] {
                    Enum.GetName(typeof(BuyChannelEnum), BuyChannelEnum.TaoBao),
                    Enum.GetName(typeof(BuyChannelEnum), BuyChannelEnum.Jd),
                    Enum.GetName(typeof(BuyChannelEnum), BuyChannelEnum.OffLine),
                    Enum.GetName(typeof(BuyChannelEnum), BuyChannelEnum.Other)
                };
                //获取今日销售购买渠道
                //线下实体店。A-销售 B-退货 C-赠送
                var posSaleFlowTodayList = await db.Set<PosSalesFlow>().Where(x => x.operateTime >= currBeginDate && x.operateTime <= currEndDate && x.saleWay == "A").AsNoTracking()?.ToListAsync();
                var computeOffLineSaleResult = posSaleFlowTodayList.GroupBy(p => new { flowNo = p.flowNo }).Select(p => new
                {
                    flowNo = p.Key.flowNo
                }).ToList();
                //淘宝，暂无

                //京东，暂无

                //列表
                foreach (var item in buyChannelList)
                {
                    //字符串转枚举
                    var buyChannelEnum = (BuyChannelEnum)Enum.Parse(typeof(BuyChannelEnum), item);
                    var buyChannelName = UtilsHelper.GetEnumDesc(buyChannelEnum);
                    if (buyChannelEnum == BuyChannelEnum.OffLine)
                    {
                        //线下实体店
                        buyChannelSale.Add(new BuyChannelSaleDto()
                        {
                            buyChannel = item,
                            buyChannelName = buyChannelName,
                            saleCount = computeOffLineSaleResult.Count
                        });
                    }
                    else if (buyChannelEnum == BuyChannelEnum.TaoBao)
                    {
                        //淘宝
                        buyChannelSale.Add(new BuyChannelSaleDto()
                        {
                            buyChannel = item,
                            buyChannelName = buyChannelName,
                            saleCount = 0
                        });
                    }
                    else if (buyChannelEnum == BuyChannelEnum.Jd)
                    {
                        //京东
                        buyChannelSale.Add(new BuyChannelSaleDto()
                        {
                            buyChannel = item,
                            buyChannelName = buyChannelName,
                            saleCount = 0
                        });
                    }
                    else
                    {
                        //其他
                        buyChannelSale.Add(new BuyChannelSaleDto()
                        {
                            buyChannel = item,
                            buyChannelName = buyChannelName,
                            saleCount = 0
                        });
                    }

                }
            }
            catch (Exception e)
            {
                _logger.LogError(message: e.Message, exception: e);
            }
            return buyChannelSale;

        }
        #endregion

        #endregion
    }
}
